/**
 * 动态边框文本DIV点
 * @class
 * @extends graphic.div.BaseDiv
 */
import BaseDiv from "./BaseDiv.js";

class DivBorderLabel extends BaseDiv {
  /**
   * 构造函数
   * @param {Object} options 配置参数
   * @param {Array.<Number>} [options.position=[111, 28, 0]] 可选 经纬度[x,y,z]
   * @param {String} [options.content] 可选 文本内容
   * @param {Object} [options.style={}] 可选 样式信息
   * @param {String} [options.style.color='#FFFFFF'] 可选 文本颜色
   * @param {Number} [options.style.fontSize=14] 可选 字体大小
   * @param {String} [options.style.borderColor='#15d1f2'] 可选 边框颜色
   * @param {String} [options.style.boxShadowColor='#15d1f2'] 可选 阴影颜色
   * @param {Number} [options.style.width=120] 可选 宽度
   * @param {Number} [options.style.height=30] 可选 高度
   * @param {Boolean} [options.style.animation=true] 可选 是否启用动画
   * @param {Cesium.DistanceDisplayCondition} [options.style.distanceDisplayCondition={ near: 0.1, far: 1000000}] 可选 可视范围
   * @param {Boolean} [options.style.pointerEvents=true] 可选 DIV是否可以鼠标交互,为false时可以穿透操作及缩放地图，但无法进行鼠标交互及触发相关事件
   * @param {Boolean} [options.style.userSelect=false] 可选 是否可以选中文本
   */
  constructor(options = {}) {
    // 初始化默认样式
    const defaultStyle = {
      color: "#FFFFFF",
      fontSize: 14,
      borderColor: "#15d1f2",
      boxShadowColor: "#15d1f2",
      width: null, // 默认null，表示根据文本内容和字体大小自动计算
      height: null, // 默认null，表示根据文本内容和字体大小自动计算
      animation: true,
      distanceDisplayCondition: { near: 0.1, far: 1000000 },
      pointerEvents: true,
      userSelect: false,
      // 存储content到style中，这样在_createDomElement中可以访问到
      _contentFromOptions: options.content || "",
    };

    // 合并样式
    const mergedOptions = {
      ...options,
      style: { ...defaultStyle, ...(options.style || {}) },
    };

    // 在子类构造函数中必须先调用super()，这是JavaScript类继承的基本规则
    super(mergedOptions);

    // 然后才能使用this关键字初始化内容
    this._content = options.content || "";

    // DOM元素已经在父类初始化时创建完成
    // 现在更新标签样式，确保所有样式正确应用
    this._updateLabelStyle();
  }

  /**
   * 获取或设置内容
   * @type {String}
   */
  get content() {
    return this._content;
  }

  set content(value) {
    if (this._content !== value) {
      this._content = value;
      this._updateLabelStyle();
      this.fire("contentChanged", { content: value });
    }
  }

  /**
   * 获取图元包围球
   * @readonly
   * @type {Cesium.BoundingSphere}
   */
  get boundingSphere() {
    // 使用父类的实现，基于position计算包围球
    return super.boundingSphere;
  }

  /**
   * 获取图元坐标 (笛卡尔)
   * @readonly
   * @type {Cesium.Cartesian3|null}
   */
  get cartesian3() {
    return super.cartesian3;
  }

  /**
   * 获取图元坐标串（笛卡尔）
   * @readonly
   * @type {Array.<Cesium.Cartesian3>}
   */
  get cartesian3Array() {
    return super.cartesian3Array;
  }

  /**
   * 获取几何坐标
   * @readonly
   * @type {Array}
   */
  get coordinates() {
    return super.coordinates;
  }

  /**
   * 获取图元所属分类
   * @readonly
   * @type {String}
   */
  get graphicClassType() {
    return "DIV";
  }

  /**
   * 获取图元类型
   * @readonly
   * @type {String}
   */
  get graphicType() {
    return "DIV_BORDER_LABEL";
  }

  /**
   * 获取图元类型名称
   * @readonly
   * @type {String}
   */
  get typeName() {
    return "DivBorderLabel";
  }

  /**
   * 设置图元坐标
   * @param {Array} position 坐标值，[x,y,z]
   */
  setPosition(position) {
    super.setPosition(position);
    // 触发位置更新事件
    this.fire("positionChanged", { position: position });
  }

  /**
   * 创建DOM元素
   * @private
   * @returns {HTMLElement}
   */
  _createDomElement() {
    // 创建外层容器
    const container = document.createElement("div");
    container.id = this.id;
    container.className =
      "cesium-extensions-div-base cesium-extensions-div-border-label";

    // 创建边框元素
    this._borderElement = document.createElement("div");
    this._borderElement.className = "cesium-extensions-div-border-label-border";

    // 创建文本元素
    this._textElement = document.createElement("span");
    this._textElement.className = "cesium-extensions-div-border-label-text";

    // 获取content内容
    // 在super调用过程中，this._content还未初始化，所以我们从style中获取存储的值
    const content = this._style._contentFromOptions || "";
    this._textElement.textContent = content;

    // 组装DOM结构 - 按照参考实现，文本元素应在边框元素内部
    this._borderElement.appendChild(this._textElement);
    container.appendChild(this._borderElement);

    return container;
  }

  /**
   * 更新标签样式和内容
   * @private
   */
  _updateLabelStyle() {
    const style = this._style;
    const domEle = this._domEle;

    if (!domEle || !this._borderElement || !this._textElement) return;

    // 设置文本内容
    this._textElement.textContent = this._content;

    // 计算尺寸相关CSS变量值
    // 计算实际使用的宽度和高度（如果用户指定了就使用用户指定的值，否则自动计算）
    let calculatedWidth = style.width;
    let calculatedHeight = style.height;

    // 如果用户没有指定宽度或高度，自动计算
    if (calculatedWidth === null || calculatedHeight === null) {
      // 使用缓存的临时测量元素，避免重复创建DOM元素
      if (!this._tempMeasureElement) {
        this._tempMeasureElement = document.createElement("span");
        this._tempMeasureElement.style.position = "absolute";
        this._tempMeasureElement.style.visibility = "hidden";
        this._tempMeasureElement.style.whiteSpace = "nowrap";
        this._tempMeasureElement.style.fontFamily = "微软雅黑";
        this._tempMeasureElement.style.fontWeight = "bolder";
        document.body.appendChild(this._tempMeasureElement);
      }

      // 设置测量参数
      this._tempMeasureElement.textContent = this._content;
      this._tempMeasureElement.style.fontSize = `${style.fontSize}px`;
      this._tempMeasureElement.style.padding = "0 10px"; // 添加左右内边距，使文本不会紧贴边框

      // 获取文本尺寸
      const textWidth = this._tempMeasureElement.offsetWidth;
      const textHeight = this._tempMeasureElement.offsetHeight;

      // 根据文本尺寸计算面板尺寸，添加适当的边距
      if (calculatedWidth === null) {
        calculatedWidth = textWidth + 10; // 添加额外的左右边距
      }
      if (calculatedHeight === null) {
        calculatedHeight = Math.max(textHeight + 10, 24); // 添加额外的上下边距，确保最小高度
      }
    }

    // 参考实现中clip尺寸比实际尺寸稍大
    const width =
      typeof calculatedWidth === "number"
        ? `${calculatedWidth}px`
        : calculatedWidth;
    const height =
      typeof calculatedHeight === "number"
        ? `${calculatedHeight}px`
        : calculatedHeight;
    const clipWidth =
      typeof calculatedWidth === "number" ? `${calculatedWidth + 15}px` : width;
    const clipHeight =
      typeof calculatedHeight === "number"
        ? `${calculatedHeight + 10}px`
        : height;
    const clipWidth2 =
      typeof calculatedWidth === "number" ? `${calculatedWidth + 13}px` : width;
    const clipHeight2 =
      typeof calculatedHeight === "number"
        ? `${calculatedHeight + 8}px`
        : height;

    // 创建样式对象一次性设置CSS变量
    const cssVars = {
      "--text-font-size": `${style.fontSize}px`,
      "--border-width": width,
      "--clip-width-1": clipWidth,
      "--clip-width-2": clipWidth2,
      "--border-height": height,
      "--clip-height-1": clipHeight,
      "--clip-height-2": clipHeight2,
      "--text-color": style.color,
      "--border-color": style.borderColor,
      "--animation-name": style.animation
        ? "cesium-extensions-div-border-label-animation"
        : "none",
    };

    // 设置box-shadow-color，添加透明度以匹配参考实现
    const boxShadowColor = style.boxShadowColor || style.borderColor;
    let rgbaColor = boxShadowColor;
    // 如果不是rgba格式且是十六进制颜色，转换为rgba并添加透明度
    if (boxShadowColor.startsWith("#") && boxShadowColor.length === 7) {
      const r = parseInt(boxShadowColor.slice(1, 3), 16);
      const g = parseInt(boxShadowColor.slice(3, 5), 16);
      const b = parseInt(boxShadowColor.slice(5, 7), 16);
      rgbaColor = `rgba(${r},${g},${b},0.5)`;
    }
    cssVars["--box-shadow-color"] = rgbaColor;

    // 批量设置CSS变量，减少DOM操作次数
    Object.entries(cssVars).forEach(([key, value]) => {
      domEle.style.setProperty(key, value);
    });

    // 设置交互属性
    domEle.style.pointerEvents =
      style.pointerEvents === false ? "none" : "auto";

    // 设置文本选择属性
    this._textElement.style.userSelect = style.userSelect ? "text" : "none";

    // 设置字体样式
    this._textElement.style.fontFamily = "微软雅黑";
  }

  /**
   * 更新DOM样式
   * @private
   * @param {HTMLElement} [element=this._domEle] 要更新样式的元素
   */
  _updateDomStyle(element = this._domEle) {
    if (!element) return;

    // 不调用父类的_updateDomStyle方法，避免样式冲突
    this._updateLabelStyle(); // _updateLabelStyle中已包含了所有必要的样式设置
  }

  /**
   * 销毁对象
   */
  destroy() {
    if (this.isDestroyed()) {
      return;
    }

    // 移除临时测量元素（如果存在）
    if (
      this._tempMeasureElement &&
      document.body.contains(this._tempMeasureElement)
    ) {
      document.body.removeChild(this._tempMeasureElement);
      this._tempMeasureElement = null;
    }

    // 清理DOM元素引用
    this._borderElement = null;
    this._textElement = null;
    this._content = null;

    // 调用父类销毁方法
    super.destroy();
  }
}

export default DivBorderLabel;
